<template>
  <div class="editor-container">
    <!-- v-show="Toolbarshow" -->
    <Toolbar :mode="mode" :editor="instance" :defaultConfig="toolbarConfig" :style="{
      border: '1px solid #ccc ',
      zIndex: Number(zIndex) + 1,
    }" />
    <Editor class="editor" :mode="mode" :defaultConfig="config" :style="{
      minHeight: height,
      height: height,
      border: '1px solid #ccc',
      backgroundColor: '#fff',
      zIndex,
    }" v-model="valueHtml" @onChange="onChange" @onFocus="handleFocus" @onBlur="handleBlur" @customPaste="customPaste"
      @onCreated="handleCreated" />
  </div>
</template>
<script setup lang="ts">
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
import "@wangeditor/editor/dist/css/style.css";
import { ElMessage } from "element-plus";
/**
 * 格式化html
 * @param val 粘贴的html
 * @author liuwei
 */

import { IDomEditor, IEditorConfig, IToolbarConfig } from "@wangeditor/editor";
import {
  computed,
  onBeforeUnmount,
  onMounted,
  reactive,
  ref,
  shallowRef,
  watch,
} from "vue";
import updateoss from "../../util/updateoss";
export type Emenu = Array<
  | "head"
  | "bold"
  | "fontSize"
  | "fontName"
  | "italic"
  | "underline"
  | "strikeThrough"
  | "indent"
  | "lineHeight"
  | "foreColor"
  | "backColor"
  | "link"
  | "list"
  | "todo"
  | "justify"
  | "quote"
  | "emoticon"
  | "image"
  | "video"
  | "table"
  | "code"
  | "splitLine"
  | "undo"
  | "redo"
>;

type InsertFnType = (url: string, alt: string, href: string) => void;

type Porps = {
  value?: string;
  menu?: Emenu;
  change?: (val: string) => void;
  zIndex?: number | string;
  editorId?: string
  height?: string
  mode?: string
  handleFocus?: (...payload: any[]) => void
  handleBlur?: (...payload: any[]) => void
  context?: string
  placeholder?: string
  Toolbarshow?: boolean
};

const prop = withDefaults(defineProps<Porps>(), {
  zIndex: 10,
  editorId: "editorId" + Date.now(),
  height: '50px',
  mode: 'default',
  handleFocus: () => { },
  handleBlur: () => { },
  Toolbarshow: true,
  value: '',
  placeholder: '',
})

const instance = shallowRef<IDomEditor>();
const value = computed(() => {
  return prop.value;
});
const content = reactive({
  html: "",
  text: "",
});
const config = reactive<Partial<IEditorConfig>>({
  autoFocus: false,
  placeholder: prop.placeholder,
  MENU_CONF: {
    uploadImage: {
      customUpload: async function (
        resultFiles: File | File[],
        insertImgFn: InsertFnType
      ) {
        // resultFiles 是 input 中选中的文件列表
        // insertImgFn 是获取图片 url 后，插入到编辑器的方法
        // 上传图片，返回结果，将图片插入到编辑器中
        const { name } = await updateoss(Array.isArray(resultFiles) ? resultFiles : [resultFiles]);
        insertImgFn(
          `https://cdn.hterobot.com/${name}`,
          name,
          `https://cdn.hterobot.com/${name}`
        );
      },
    },
    uploadVideo: {
      customUpload: async (
        resultFiles: File | File[],
        insertFn: InsertFnType
      ) => {
        // res 即服务端的返回结果
        const { name } = await updateoss(
          Array.isArray(resultFiles) ? resultFiles : [resultFiles]
        );
        insertFn(
          `https://cdn.hterobot.com/${name}`,
          name,
          `https://cdn.hterobot.com/${name}`
        );
      },
    },
  },
  customAlert: (s: string, t: string) => {
    switch (t) {
      case "success":
        ElMessage.success(s);
        break;
      case "info":
        ElMessage.info(s);
        break;
      case "warning":
        ElMessage.warning(s);
        break;
      case "error":
        ElMessage.error(s);
        break;
      default:
        ElMessage.info(s);
        break;
    }
  },
});

onMounted(() => {
  handleCreated(instance.value);
})

/**
 * 粘贴
 */
function customPaste(editor: any, event: any, callback: Function) {
  const text = event.clipboardData?.getData('text/plain') // 获取粘贴的纯文本
  editor.insertText(text)
  event.preventDefault()
  callback(false)
}

const toolbarConfig = reactive<Partial<IToolbarConfig>>({
  excludeKeys: [
    "lineHeight",
    "italic",
    "fullScreen",
    "todo",
    "redo",
    "undo",
    "numberedList",
    "bgColor",
    "|",]
})

function onChange() {
  if (instance.value) {
    const t = instance.value.getHtml();
    if (t && prop.change) {
      prop.change(t);
    }
  }
}

const valueHtml = ref('')
function handleCreated(editor?: IDomEditor) {
  if (editor) {
    instance.value = editor;
    valueHtml.value = value.value || ''
  }
}

function removeNodes() {
  instance.value?.clear();
}

watch(
  () => value.value,
  () => {
    handleCreated(instance.value);
  }
);

onBeforeUnmount(() => {
  if (instance.value == null) return;
  // 销毁，并移除 editor
  instance.value.destroy();
  // removeEditor(prop.editorId);
});
const syncHTML = () => {
  content.html = instance.value?.getHtml() || "";
  return content.html;
};
function gethtml() {
  return valueHtml.value || ''
}
function gettext() {
  return instance.value?.getText() || "";
}
function getcontext() {
  return JSON.stringify(instance.value?.children || []);
}

defineExpose({
  syncHTML,
  gethtml,
  editorConfig: config,
  onChange,
  removeNodes,
  gettext,
  getcontext,
  handleCreated,
  instance
})
</script>

<style scoped>
.editor {
  max-width: 100%;
  transition: all ease-out 0.3s;
}
</style>

<style>
/* 解决 warning：编辑区域高度<300px 这可能会导致model hoverbar定位异常 */
.editor-container .w-e-scroll {
  height: 500px;
  position: relative;
  z-index: 0;
}

.editor-container .w-e-text-container {
  overflow: hidden;
}
</style>